-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Meshing for Triangle3d
primitive
#12686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lovely! Looks all correct to me. Really appreciate the comments on the UVs. The new UV layout seems like an unambiguous improvement too.
Do you think we could get this added to one of the primitive examples, now that it's meshed?
let [a, b, c] = self.vertices; | ||
let vertices_3d = self.vertices.map(|v| v.extend(0.)); | ||
|
||
let positions = vec![[a.x, a.y, 0.0], [b.x, b.y, 0.0], [c.x, c.y, 0.0]]; | ||
let positions: Vec<_> = vertices_3d.into(); | ||
let normals = vec![[0.0, 0.0, 1.0]; 3]; | ||
|
||
// The extents of the bounding box of the triangle, | ||
// used to compute the UV coordinates of the points. | ||
let extents = a.min(b).min(c).abs().max(a.max(b).max(c)) * Vec2::new(1.0, -1.0); | ||
let uvs = vec![ | ||
a / extents / 2.0 + 0.5, | ||
b / extents / 2.0 + 0.5, | ||
c / extents / 2.0 + 0.5, | ||
]; | ||
let uvs: Vec<_> = triangle3d::uv_coords(&Triangle3d::new( | ||
vertices_3d[0], | ||
vertices_3d[1], | ||
vertices_3d[2], | ||
)) | ||
.into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✨fancy✨
@@ -4,6 +4,7 @@ mod cylinder; | |||
mod plane; | |||
mod sphere; | |||
mod torus; | |||
pub(crate) mod triangle3d; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this in a different format to the other module declarations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's pub(crate) so that the Triangle2d
code can see the Triangle3d
UV generation code. Maybe there's a more elegant way to accomplish that, but this seemed like the simplest thing at the time.
Co-authored-by: Jakub Marcowski <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks solid to me. I'd like to see this in an example too, but I won't block on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good, changes made sound reasonable.
Co-authored-by: Jakub Marcowski <[email protected]>
Co-authored-by: Jakub Marcowski <[email protected]>
@mweatherley I couldn't immediately get the formatting right when resolving merge conflicts. Ping me when it's fixed up and I'll merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How peculiar, my previous fmt review comment was actually a copy-paste of the CI's suggestion. Weird how that wasn't the final, desirable version.
Objective
Meshable
trait forTriangle3d
, allowing 3d triangle primitives to produce meshes.Solution
The
Meshable
trait forTriangle3d
directly produces aMesh
, much like that ofTriangle2d
. The mesh consists only of a single triangle (the triangle itself), and its vertex data consists of:Triangle2d
which, because of its lower dimension, has an orientation which can be corrected for so that it always faces "the right way")ab
direction of the triangle.Here is a visual demonstration; here, the
ab
direction of the triangle is horizontal, left to right — the pointc
moves, expanding the bounding rectangle of the triangle when it pushes pasta
orb
:The UV-mapping of
Triangle2d
has also been changed to use the same logic.Changelog
Meshable
forTriangle3d
.Triangle2d
to match that ofTriangle3d
.Migration Guide
The UV-mapping of
Triangle2d
has changed with this PR; the main difference is that the UVs are no longer dependent on the triangle's absolute coordinates, but instead follow translations of the triangle itself in its definition. If you depended on the old UV-coordinates forTriangle2d
, then you will have to update affected areas to use the new ones which, briefly, can be described as follows:Generally speaking, this means that the first two points will have coordinates
[_, 0.]
, while the third coordinate will be[_, 1.]
, with the exact values depending on the position of the third point relative to the first two. For acute triangles, the first two vertices always have UV-coordinates[0., 0.]
and[1., 0.]
respectively. For obtuse triangles, the third point will have coordinate[0., 1.]
or[1., 1.]
, with the coordinate of one of the two other points shifting to maintain proportionality.For example:
Triangle2d
has UV-coordinates[0., 0.]
,[0., 1.]
, [0.5, 1.]
.vec2(0., 0.)
,vec2(1., 0.)
,vec2(2., 1.)
has UV-coordinates[0., 0.]
,[0.5, 0.]
,[1., 1.]
.vec2(0., 0.)
,vec2(1., 0.)
,vec2(-2., 1.)
has UV-coordinates[2./3., 0.]
,[1., 0.]
,[0., 1.]
.Discussion
Design considerations
bc
so that the vertices are always[0., 0.]
,[0., 1.]
, and[1., 0.]
. I chose this method instead because it is skew-free, so that the sampling from textures has only bilinear scaling. I think this is better for cases where a relatively "uniform" texture is mapped to the triangle, but it's possible that we might want to support the other thing in the future. Thankfully, we already have the capability of easily expanding to do that with Builders if the need arises. This could also allow us to provide things like barycentric subdivision.Triangle3d
is set up to never fail, even in the case that the triangle is degenerate. I have mixed feelings about this, but none of our other primitive meshes fail, so I decided to take the same approach. Maybe this is something that could be worth revisiting in the future across the board.